#pragma once
#include <string>
#include <vector>
#include <time.h>
#include <curl/curl.h>
#include "BBS2chProxyThreadInfo.h"
#include "BBS2chProxyHttpHeaders.h"
#include "parson/parson.h"

class IBBS2chProxyHTML2Dat {
protected:
	BBS2chProxyThreadCache *_threadCache;
	std::string _url;
	std::string _threadKey;
	std::string _userAgent;
	CURL *_curl;
public:
	IBBS2chProxyHTML2Dat(BBS2chProxyThreadCache *cache, const BBS2chThreadIdentifier &identifier, CURL *curl)
	 : _threadCache(cache), _curl(curl)
	{
		_threadKey = identifier.host;
		_threadKey += '/';
		_threadKey += identifier.board;
		_threadKey += '/';
		_threadKey += identifier.key;
	};
	virtual ~IBBS2chProxyHTML2Dat() {};
	virtual std::string generateDatFrom(int startFrom, time_t *lastModifiedOut, bool useCache, long *outStatusCode) = 0;
	void setRequestHeaders(BBS2chProxyHttpHeaders &headers);
	const std::string& getKey();
protected:
	std::vector<char> getHtmlFromURL(const std::string &url, long *outStatusCode);
};

class BBS2chProxyHTML2Dat5ch : public IBBS2chProxyHTML2Dat {
public:
	BBS2chProxyHTML2Dat5ch(BBS2chProxyThreadCache *cache, const BBS2chThreadIdentifier &identifier, bool useHttps, CURL *curl);
	~BBS2chProxyHTML2Dat5ch() {};
	virtual std::string generateDatFrom(int startFrom, time_t *lastModifiedOut, bool useCache, long *outStatusCode);
private:
	std::string html2dat_old(std::vector<char> &html, int startResNum, time_t *lastModified, bool useCache);
	std::string html2dat(std::vector<char> &html, int startResNum, time_t *lastModified, bool useCache);
};

class BBS2chProxyHTML2DatTalk : public IBBS2chProxyHTML2Dat {
protected:
	JSON_Value *_cachedJson;
public:
	BBS2chProxyHTML2DatTalk(BBS2chProxyThreadCache *cache, const BBS2chThreadIdentifier &identifier, CURL *curl);
	virtual ~BBS2chProxyHTML2DatTalk() {
		if (_cachedJson) json_value_free(_cachedJson);
	};
	virtual std::string generateDatFrom(int startFrom, time_t *lastModifiedOut, bool useCache, long *outStatusCode);
protected:
	std::string json2dat(JSON_Value *json, int startFrom, time_t *lastModifiedOut, bool useCache);
};

class BBS2chProxyHTML2DatTalkHTML : public BBS2chProxyHTML2DatTalk {
public:
	BBS2chProxyHTML2DatTalkHTML(BBS2chProxyThreadCache *cache, const BBS2chThreadIdentifier &identifier, CURL *curl);
	virtual ~BBS2chProxyHTML2DatTalkHTML() {};
	virtual std::string generateDatFrom(int startFrom, time_t *lastModifiedOut, bool useCache, long *outStatusCode);
};

class BBS2chProxyHTML2Dat5chItest : public BBS2chProxyHTML2DatTalk {
protected:
	JSON_Value *_cachedJson;
public:
	BBS2chProxyHTML2Dat5chItest(BBS2chProxyThreadCache *cache, const BBS2chThreadIdentifier &identifier, CURL *curl);
	virtual ~BBS2chProxyHTML2Dat5chItest() {};
	virtual std::string generateDatFrom(int startFrom, time_t *lastModifiedOut, bool useCache, long *outStatusCode);
protected:
	std::string json2dat(JSON_Value *json, int startFrom, time_t *lastModifiedOut, bool useCache);
};
